#include "uart.h"


#if USE_PRINTF

#pragma import(__use_no_semihosting)  
//解决HAL库使用时,某些情况可能报错的bug
//因为禁止了半主机模式，需要重写一个半主机模式下的接口，如下
int _ttywrch(int ch)    
{
    ch=ch;
	return ch;
}
 
 
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 
}; 

 
FILE __stdout;     
 
 
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
 
 
// 重定向printf
int fputc(int ch, FILE * fp)
{
#if USE_PRINTF_UART1
    while((USART1->SR&0X40)==0);
    USART1->DR = (uint8_t)ch;
#endif

#if USE_PRINTF_UART2
    while((USART2->SR&0X40)==0);
    USART2->DR = (uint8_t)ch;
#endif
    return ch;
}
#endif


/*====================================串口1==================================*/

// 初始化串口1
void UART1_Init(uint32_t Baud)
{
    GPIO_InitTypeDef  GPIO_Initstruct;
    USART_InitTypeDef UART_Initstruct;
    NVIC_InitTypeDef NVIC_Initstruct;
   
    // 使能UART1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
    // 引脚初始化
    GPIO_Initstruct.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
    GPIO_Initstruct.GPIO_Pin = TX1_Pin;
    GPIO_Initstruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(UART1_Port, &GPIO_Initstruct);
    
    GPIO_Initstruct.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
    GPIO_Initstruct.GPIO_Pin = RX1_Pin;
    GPIO_Init(UART1_Port, &GPIO_Initstruct);
    
    UART_Initstruct.USART_BaudRate = Baud;
    UART_Initstruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控
    UART_Initstruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  // 收发模式 
    UART_Initstruct.USART_Parity = USART_Parity_No; // 无校验
    UART_Initstruct.USART_StopBits = USART_StopBits_1; // 1位校验位
    UART_Initstruct.USART_WordLength = USART_WordLength_8b; // 8位字长
    USART_Init(UART1,&UART_Initstruct);
        
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    // NVIC 中断配置
    NVIC_Initstruct.NVIC_IRQChannel = USART1_IRQn;
    NVIC_Initstruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Initstruct.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_Initstruct.NVIC_IRQChannelSubPriority = 2;
    NVIC_Init(&NVIC_Initstruct);
    
    USART_ITConfig(UART1,USART_IT_RXNE,ENABLE); // 使能接收中断
    USART_Cmd(UART1,ENABLE); // 使能串口
    
}


// 发送一字节数据
void Uart1_SendByte(uint8_t Byte)
{
    while((USART1->SR&0X40)==0);
	USART1->DR= Byte;
}

// 接收中断函数
void USART1_IRQHandler(void)
{
    // 判断是否接收到数据
    if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET)
    {
        Uart1_SendByte(USART_ReceiveData(USART1));
        
        USART_ClearITPendingBit(USART1,USART_IT_RXNE);
    }
}

/*====================================串口2==================================*/
// 串口2中断标志
uint8_t UART2_RxFlag = 0;
uint8_t UART2_RxData = 0;

// 串口2初始化函数
void UART2_Init(uint32_t Baud)
{
    USART_InitTypeDef UART_Initstruct;
    GPIO_InitTypeDef GPIO_Initstruct;
    NVIC_InitTypeDef NVIC_Initstruct;
    
    // 使能串口2时钟  
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
    // 使能GPIO时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
    GPIO_Initstruct.GPIO_Pin = TX2_Pin;
    GPIO_Initstruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Initstruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(UART2_Port,&GPIO_Initstruct);
    
    GPIO_Initstruct.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Initstruct.GPIO_Pin = RX2_Pin;
    GPIO_Init(UART2_Port,&GPIO_Initstruct);
    
    UART_Initstruct.USART_BaudRate = Baud;
    UART_Initstruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    UART_Initstruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    UART_Initstruct.USART_Parity = USART_Parity_No;
    UART_Initstruct.USART_StopBits = USART_StopBits_1;
    UART_Initstruct.USART_WordLength = USART_WordLength_8b;
    USART_Init(UART2,&UART_Initstruct);
   
    // NVIC 中断分组
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    NVIC_Initstruct.NVIC_IRQChannel = USART2_IRQn;
    NVIC_Initstruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Initstruct.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_Initstruct.NVIC_IRQChannelSubPriority = 2;
    NVIC_Init(&NVIC_Initstruct);
    
    // 配置接收中断
    USART_ITConfig(UART2,USART_IT_RXNE,ENABLE);
    // 开启串口2
    USART_Cmd(UART2,ENABLE);
}

// 发送一字节数据
void Uart2_SendByte(uint8_t Byte)
{
    while((USART2->SR&0X40)==0);
	USART2->DR= Byte;
}


#if USE_ESP8266
// 用于接收esp返回的数据
uint8_t ESP_RxData[300]; // 接收缓冲区
volatile uint8_t ESP_RxFlag = 0; // 接收完成标志

// 空闲中断接收不定长数据
void USART2_IRQHandler(void)
{
    static uint32_t cnt = 0;
    uint8_t Clear = Clear;
    uint8_t data;
    // 判断是否接收到数据
    if(USART_GetITStatus(USART2,USART_IT_RXNE) == SET)
    {
        if(cnt == 0)
        {
            // 每次接收前先清空
           memset((char *)ESP_RxData,0,sizeof(ESP_RxData));       
        }
        data = USART_ReceiveData(USART2);
        ESP_RxData[cnt++] = data;
        if(cnt >= 300)        // 如果已经超出大小,结束接收
        {
            Clear = USART2->SR;
            Clear = USART2->DR;
            cnt = 0;
            printf("%s\r\n",ESP_RxData);
            ESP_RxFlag = 1;
        }
     }
    else if(USART_GetITStatus(USART2,USART_IT_IDLE) == SET)
    {
        Clear = USART2->SR;
        Clear = USART2->DR;
        cnt = 0;
        #ifdef uart1_print_msg
            printf("%s\r\n",ESP_RxData); // 串口1打印收到的数据
        #endif
        ESP_RxFlag = 1;
    }
}

#else 
// 接收中断函数
void USART2_IRQHandler(void)
{
    // 判断是否接收到数据
    if(USART_GetITStatus(USART2,USART_IT_RXNE) == SET)
    {
        UART2_RxFlag = 1;
        UART2_RxData = USART_ReceiveData(USART2);
    }
}
#endif
